#region Copyright (C) 2005-2007 Team MediaPortal

/* 
 *	Copyright (C) 2005-2007 Team MediaPortal
 *	http://www.team-mediaportal.com
 *
 *  This Program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2, or (at your option)
 *  any later version.
 *   
 *  This Program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *  GNU General Public License for more details.
 *   
 *  You should have received a copy of the GNU General Public License
 *  along with GNU Make; see the file COPYING.  If not, write to
 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *  http://www.gnu.org/copyleft/gpl.html
 *
 */

#endregion

using System;
using System.Collections.Generic;
using System.Text;
using MediaPortal.GUI.Library;
using MediaPortal.Search;
using System.Windows.Forms;
using MediaPortal.Playlists;
using MediaPortal.Music.Database;
using MediaPortal.Dialogs;
using System.Collections;
using GlobalSearch;
using MediaPortal.Configuration;

namespace MediaPortal.GUI.GlobalSearch
{
    [PluginIcons("GlobalSearch.search_music.gif", "GlobalSearch.search_music_disabled.gif")]
    public class GUIGlobalMusicSearch : GUIWindow, ISetupForm, IShowPlugin
    {
        #region Constants
        public const int UID = 30885;
        public const string GlobalSearchPluginName = "Search music";
        #endregion

        #region Private declarations
        private bool _enteredPhrase = false;
        private GlobalMusicSearch _search = new GlobalMusicSearch();
        private bool pageInitialized = false;
        private bool autofillSearchResults = false;
        private List<GUIListItem> lastSearchResults = new List<GUIListItem>();

        [SkinControlAttribute(2)]
        protected GUIButtonControl btnSearchPhrase = null;

        [SkinControlAttribute(7)]
        protected GUIButtonControl btnLastSearches = null;

        [SkinControlAttribute(3)]
        protected GUIToggleButtonControl btnCaseSensitive = null;

        [SkinControlAttribute(5)]
        protected GUISelectButtonControl btnSearchType = null;

        [SkinControlAttribute(6)]
        protected GUIButtonControl btnSearchFields = null;

        [SkinControlAttribute(8)]
        protected GUIButtonControl btnMyMusic = null;

        [SkinControlAttribute(9)]
        protected GUIButtonControl btnPlayingNow = null;

        [SkinControlAttribute(50)]
        protected GUIFacadeControl lstResults = null;
        #endregion

        #region overrides

        protected override void OnPageLoad()
        {
            if (!pageInitialized)
            {
                pageInitialized = true;
                btnSearchType.SelectedItem = 2;
                btnSearchType.RestoreSelection = false;
                GlobalSearchSettings.Instance().LoadFromFile();
            }
            else
            {
                btnSearchType.SelectedItem = (int)_search.Type >> 1;

                if (_enteredPhrase)
                    btnSearchPhrase.Label = _search.SearchPhrase;

                ((GUIToggleButtonControl)btnCaseSensitive).Selected = _search.Options == SearchGlobals.SearchOptions.CaseSensitive;
            }

            if (autofillSearchResults)
            {
                autofillSearchResults = false;
                fillSearchResults();
            }

            base.OnPageLoad();
        }

        public override bool Init()
        {
            return Load(GUIGraphicsContext.Skin + @"\GlobalSearch.Music.xml");
        }

        public override int GetID
        {
            get
            {
                return GUIGlobalMusicSearch.UID;
            }
        }

        public override void OnAction(Action action)
        {
            base.OnAction(action);
        }

        public static void PlayNow(Song song)
        {
            PlayListPlayer.SingletonPlayer.g_Player.Stop();
            ClearPlaylist();
            AddSongToPlaylist(song);
        }

        public static void PlayNext(Song song)
        {
            PlayListPlayer playlistPlayer = PlayListPlayer.SingletonPlayer;
            PlayList playList = playlistPlayer.GetPlaylist(PlayListType.PLAYLIST_MUSIC);

            int index = Math.Max(playlistPlayer.CurrentSong, 0);

            if (playList.Count == 1)
            {
                AddSongToPlaylist(song);
            }

            if (playList.Count > 1)
            {
                PlayListItem _pi = new PlayListItem(song.Title, song.FileName, song.Duration);
                playList.Insert(_pi, index);
            }
            else
            {
                playlistPlayer.CurrentPlaylistType = PlayListType.PLAYLIST_MUSIC;
                AddSongToPlaylist(song);
            }

            if (!playlistPlayer.g_Player.Playing)
            {
                playlistPlayer.CurrentPlaylistType = PlayListType.PLAYLIST_MUSIC;
                playlistPlayer.Play(index);
            }
        }

        public static void AddAlbumToPlayList(Song song)
        {
            PlayListPlayer playlistPlayer = PlayListPlayer.SingletonPlayer;
            PlayList playList = playlistPlayer.GetPlaylist(PlayListType.PLAYLIST_MUSIC);
            GUIDialogYesNo _dlgYesNo = (GUIDialogYesNo)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_YES_NO);
            _dlgYesNo.SetHeading(136);
            _dlgYesNo.SetLine(1, "Clear playlist?");
            _dlgYesNo.DoModal(GUIWindowManager.ActiveWindow);

            if (_dlgYesNo.IsConfirmed)
            {
                ClearPlaylist();
                playlistPlayer.g_Player.Stop();
            }

            ArrayList _album = new ArrayList();
            String sAlbum = song.Album;
            MusicDatabase _mdb = MusicDatabase.Instance;
            bool _songsFound = _mdb.GetSongsByAlbum(sAlbum, ref _album);

            if (_songsFound)
            {
                for (int i = 0; i < _album.Count; i++)
                {
                    playList.Remove(((Song)_album[i]).FileName);
                    AddSongToPlaylist((Song)_album[i], false);
                }

                if (!playlistPlayer.g_Player.Playing)
                {
                    playlistPlayer.Play(0);
                }
            }
        }

        public static void AddSongToFavorites(Song song)
        {
            song.Favorite = true;
            MusicDatabase _mdb = MusicDatabase.Instance;
            _mdb.SetFavorite(song);
        }

        protected override void OnShowContextMenu()
        {
            GUIListItem _item = lstResults.SelectedListItem;
            GUIDialogMenu _dlg = (GUIDialogMenu)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_MENU);
            _dlg.SetHeading(424);
            _dlg.AddLocalizedString(4552); // Play now
            _dlg.AddLocalizedString(4551); // Play next
            _dlg.AddLocalizedString(926); // Add to playlist
            _dlg.AddLocalizedString(4557); // Add all to playlist
            _dlg.AddLocalizedString(33041); // Add album to playlist
            _dlg.AddLocalizedString(930); // Add to favorites
            _dlg.DoModal(GUIWindowManager.ActiveWindow);

            if (_dlg.SelectedLabel == -1)
                return;

            Song _song = new Song();
            MusicDatabase _mdb = MusicDatabase.Instance;
            _mdb.GetSongByFileName(_item.Path, ref _song);

            if (_song == null)
                return;

            switch (_dlg.SelectedId)
            {
                case 4552:
                    {
                        PlayNow(_song);
                        break;
                    }

                case 4551:
                    {
                        PlayNext(_song);
                        break;
                    }

                case 926:
                    {
                        AddSongToPlaylist(_song);
                        break;
                    }

                case 4557:
                    {
                        AddAllToPlaylist();
                        break;
                    }

                case 33041:
                    {
                        AddAlbumToPlayList(_song);
                        break;
                    }

                case 930:
                    {
                        AddSongToFavorites(_song);
                        break;
                    }
            }

        }

        private void AddAllToPlaylist()
        {
            MusicDatabase _mdb = MusicDatabase.Instance;
            PlayListPlayer playListPlayer = PlayListPlayer.SingletonPlayer;
            PlayList playList = playListPlayer.GetPlaylist(PlayListType.PLAYLIST_MUSIC);
            Song firstSong = null;

            GUIDialogYesNo _dlgYesNo = (GUIDialogYesNo)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_YES_NO);
            _dlgYesNo.SetHeading(136);
            _dlgYesNo.SetLine(1, "Clear playlist?");
            _dlgYesNo.DoModal(GUIWindowManager.ActiveWindow);

            if (_dlgYesNo.IsConfirmed)
            {
                ClearPlaylist();
                playListPlayer.g_Player.Stop();
            }

            foreach (GUIListItem li in lastSearchResults)
            {
                Song _song = new Song();
                _mdb.GetSongByFileName(li.Path, ref _song);

                PlayListItem _pi = new PlayListItem(_song.Title, _song.FileName, _song.Duration);
                playList.Add(_pi);

                if (firstSong == null)
                {
                    firstSong = _song;
                }
            }

            if ((firstSong != null) && (!playListPlayer.g_Player.Playing))
            {
                playListPlayer.CurrentPlaylistType = PlayListType.PLAYLIST_MUSIC;
                playListPlayer.Play(0);
            }
        }

        private bool GetInputString(ref string input, int x, int y)
        {
            bool result = false;
            // Replace the virtual Keyboard with our own;      
            if (GlobalSearchSettings.Instance().KeyboardType == KeyboardType.NormalVirtualKeyboard)
            {
                VirtualKeyboard keyboard = (VirtualKeyboard)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_VIRTUAL_KEYBOARD);

                if (null == keyboard) return false;
                string searchterm = string.Empty;
                keyboard.Reset();
                keyboard.IsSearchKeyboard = false;
                keyboard.Location = new MediaPortal.Drawing.Point(x, y);
                keyboard.Text = input;
                keyboard.DoModal(GetID); // show it...

                // If input is finished, the string is saved to the searchterm var.
                if (keyboard.IsConfirmed)
                    searchterm = keyboard.Text;

                input = searchterm;
                result = true;
            }

            if (GlobalSearchSettings.Instance().KeyboardType == KeyboardType.SMSVirtualKeyboard)
            {
                VirtualKeyboard originalKeyboard = (VirtualKeyboard)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_VIRTUAL_KEYBOARD);
                SMSStyledKeyboard keyboard = new SMSStyledKeyboard();
                keyboard.Init();
                GUIWindowManager.Replace((int)GUIWindow.Window.WINDOW_VIRTUAL_KEYBOARD, (GUIWindow)keyboard);

                if (null == keyboard) return false;
                string searchterm = string.Empty;
                keyboard.Reset();
                keyboard.IsSearchKeyboard = false;
                keyboard.Location = new MediaPortal.Drawing.Point(x, y);
                keyboard.Text = input;
                keyboard.DoModal(GetID); // show it...

                // If input is finished, the string is saved to the searchterm var.
                if (keyboard.IsConfirmed)
                    searchterm = keyboard.Text;

                input = searchterm;

                //Restore original Keyboard
                GUIWindowManager.Replace((int)GUIWindow.Window.WINDOW_VIRTUAL_KEYBOARD, (GUIWindow)originalKeyboard);
                result = true;
            }

            return result;
        }

        protected void fillSearchResults()
        {
            GUIControl.ClearControl(GetID, 50);
            foreach (GUIListItem searchItem in lastSearchResults)
            {
                GUIControl.AddListItemControl(GetID, 50, searchItem);
            }
        }

        public static string GetCoverArtFilename(String songFilename)
        {
            string smallCoverArt = MediaPortal.Util.Utils.GetCoverArt(System.IO.Path.GetDirectoryName(songFilename), "folder");
            string largeCoverArt = MediaPortal.Util.Utils.GetLargeCoverArtName(System.IO.Path.GetDirectoryName(songFilename), "folder");

            try
            {
                if (System.IO.File.Exists(smallCoverArt))
                {
                    return smallCoverArt;
                }
                else
                {
                    if (System.IO.File.Exists(largeCoverArt))
                    {
                        return largeCoverArt;
                    }
                    else
                    {
                        return "";
                    }
                }
            }
            catch (Exception e)
            {
                MediaPortal.GUI.Library.Log.Error(e);
                return "";
            }
        }

        private void DoSearch()
        {
            if (!_enteredPhrase)
            {
                GUIDialogOK _dialog = (GUIDialogOK)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_OK);
                _dialog.SetHeading(257);
                _dialog.SetLine(1, 2500);
                _dialog.DoModal(GUIWindowManager.ActiveWindow);
            }
            else
            {
                _search.Type = (MediaPortal.Search.SearchGlobals.SearchType)(1 << btnSearchType.SelectedItem);

                GUIDialogProgress dlgProgress = (GUIDialogProgress)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_PROGRESS);
                if (dlgProgress != null)
                {
                    dlgProgress.SetHeading(194);
                    dlgProgress.SetLine(1, "Please wait...");
                    dlgProgress.StartModal(GUIWindowManager.ActiveWindow);
                    dlgProgress.Progress();
                }

                MediaPortal.Search.GlobalSearch mySearcher = new MediaPortal.Search.GlobalSearch();
                mySearcher.Methods.Add(_search);
                mySearcher.Search();
                GlobalSearchSettings.Instance().LastSearchItems.registerNewSearch(_search.SearchPhrase, _search.Type, _search.Options);

                lastSearchResults.Clear();
                foreach (SearchResult searchItem in mySearcher.Results)
                {
                    try
                    {
                        GUIListItem _item = new GUIListItem();
                        _item.Label = searchItem.Item;
                        _item.Label2 = searchItem.Source;
                        _item.Path = searchItem.Filename;
                        try
                        {
                            _item.IconImage = GetCoverArtFilename(searchItem.Filename);
                        }
                        catch (Exception e)
                        {
                            ;
                        }

                        lastSearchResults.Add(_item);
                    }
                    catch (Exception e)
                    {
                        dlgProgress.SetLine(1, "Search failed!");
                        dlgProgress.SetLine(2, e.Message);
                        throw;
                    }

                }

                fillSearchResults();

                if (dlgProgress != null) dlgProgress.Close();

                GUIControl.FocusControl(GetID, lstResults.GetID);
            }
        }

        public static void ClearPlaylist()
        {
            PlayListPlayer playListPlayer = PlayListPlayer.SingletonPlayer;
            PlayList playList = playListPlayer.GetPlaylist(PlayListType.PLAYLIST_MUSIC);
            playList.Clear();
        }

        public static void AddSongToPlaylist(Song song, bool autoPlayWhenNothingInList)
        {
            PlayListPlayer playListPlayer = PlayListPlayer.SingletonPlayer;
            PlayList playList = playListPlayer.GetPlaylist(PlayListType.PLAYLIST_MUSIC);
            PlayListItem _pi = new PlayListItem(song.Title, song.FileName, song.Duration);
            playList.Add(_pi);
            if ((autoPlayWhenNothingInList) && (!playListPlayer.g_Player.Playing))
            {
                playListPlayer.CurrentPlaylistType = PlayListType.PLAYLIST_MUSIC;
                playListPlayer.Play(0);
            }
        }
        public static void AddSongToPlaylist(Song song)
        {
            AddSongToPlaylist(song, true);
        }

        private void HandleListViewClick(GUIControl control)
        {
            if (control != null)
            {
                GUIGlobalMusicSearchDetail _searchDetail = (GUIGlobalMusicSearchDetail)GUIWindowManager.GetWindow(GUIGlobalMusicSearchDetail.UID);
                GUIListItem _item = ((GUIFacadeControl)control).SelectedListItem;

                Song _song = new Song();
                MusicDatabase _mdb = MusicDatabase.Instance;
                if (_mdb.GetSongByFileName(_item.Path, ref _song))
                {
                    autofillSearchResults = true;
                    GUIWindowManager.ActivateWindow(GUIGlobalMusicSearchDetail.UID);
                    _searchDetail.SetSong(_song);
                }
                else
                {
                    GUIDialogOK _seldialog = (GUIDialogOK)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_OK);
                    _seldialog.SetHeading(1020);
                    _seldialog.SetLine(1, "File not found!");
                    _seldialog.DoModal(GUIWindowManager.ActiveWindow);
                }
            }
        }
        public static void OpenPlayingNow()
        {
            int iWindowId = (int)GUIWindow.Window.WINDOW_MUSIC_PLAYING_NOW;
            GUIWindowManager.ActivateWindow(iWindowId);
        }

        public static void OpenMyMusic()
        {
            int iWindowId = (int)GUIWindow.Window.WINDOW_MUSIC_PLAYLIST;
            GUIWindowManager.ActivateWindow(iWindowId);
        }

        protected override void OnClicked(int controlId, GUIControl control, Action.ActionType actionType)
        {
            if (control == btnSearchPhrase)
            {
                string refvalue = (_enteredPhrase ? btnSearchPhrase.Label : "");
                //if ((GetKeyboard(ref refvalue)) && (refvalue.Trim() != ""))
                if ((GetInputString(ref refvalue, control.XPosition, control.YPosition)) && (refvalue.Trim() != ""))
                {
                    _search.SearchPhrase = refvalue;
                    btnSearchPhrase.Label = refvalue;
                    _enteredPhrase = true;
                    DoSearch();
                }
            }

            if (control == btnCaseSensitive)
            {
                GUIToggleButtonControl _control = (GUIToggleButtonControl)control;
                _search.Options = (_control.Selected ? SearchGlobals.SearchOptions.CaseSensitive : SearchGlobals.SearchOptions.CaseInsensitive);
            }

            if (control == btnMyMusic)
            {
                autofillSearchResults = true;
                OpenMyMusic();
                return;
            }

            if (control == btnPlayingNow)
            {
                autofillSearchResults = true;
                OpenPlayingNow();
                return;
            }

            if (control == btnCaseSensitive)
            {
                GUIToggleButtonControl _control = (GUIToggleButtonControl)control;
                _search.Options = (_control.Selected ? SearchGlobals.SearchOptions.CaseSensitive : SearchGlobals.SearchOptions.CaseInsensitive);
            }

            if (control == btnLastSearches)
            {
                GUIDialogMenu _dlg = (GUIDialogMenu)GUIWindowManager.GetWindow((int)GUIWindow.Window.WINDOW_DIALOG_MENU);
                _dlg.SetHeading(424);
                foreach (LastSearchItem lsi in GlobalSearchSettings.Instance().LastSearchItems)
                {
                    _dlg.Add(lsi.Phrase);
                }
                _dlg.DoModal(GUIWindowManager.ActiveWindow);

                if (_dlg.SelectedLabel == -1)
                    return;

                LastSearchItem myLsi = GlobalSearchSettings.Instance().LastSearchItems[_dlg.SelectedLabel];
                _search.SearchPhrase = myLsi.Phrase;
                _search.Options = myLsi.SearchOptions;
                _search.Type = myLsi.SearchType;
                btnSearchPhrase.Label = _search.SearchPhrase;

                if (_search.Type == SearchGlobals.SearchType.Equals)
                {
                    btnSearchType.SelectedItem = 0;
                }
                if (_search.Type == SearchGlobals.SearchType.StartsWith)
                {
                    btnSearchType.SelectedItem = 1;
                }
                if (_search.Type == SearchGlobals.SearchType.Contains)
                {
                    btnSearchType.SelectedItem = 2;
                }
                if (_search.Type == SearchGlobals.SearchType.EndsWith)
                {
                    btnSearchType.SelectedItem = 3;
                }

                btnCaseSensitive.Selected = (_search.Options == SearchGlobals.SearchOptions.CaseSensitive);
                _enteredPhrase = true;
                DoSearch();
            }

            if (control == btnSearchFields)
            {
                GUIDialogMultiSelect _dialog = (GUIDialogMultiSelect)GUIWindowManager.GetWindow(2100);
                _dialog.SetHeading("Select search fields");
                _dialog.Reset();

                GUIListItem _item = null;

                for (int i = 0; i < GlobalMusicSearch.SearchFieldValues.Count; i++)
                {
                    _item = new GUIListItem(GlobalMusicSearch.SearchFieldTranslatedStrings[i]);
                    _item.MusicTag = GlobalMusicSearch.SearchFieldValues[i];
                    _item.Selected = _search.ContainsSearchField((GlobalMusicSearch.MusicSearchFields)_item.MusicTag);
                    _dialog.Add(_item);
                }

                _dialog.DoModal(GUIWindowManager.ActiveWindow);

                if (_dialog.DialogModalResult == ModalResult.OK)
                {

                    _search.EmptySearchFields();
                    for (int i = 0; i < _dialog.ListItems.Count; i++)
                    {
                        if (_dialog.ListItems[i].Selected)
                        {
                            _search.IncludeSearchFields((GlobalMusicSearch.MusicSearchFields)_dialog.ListItems[i].MusicTag);
                        }
                    }
                }
            }

            if (controlId == 50)
            {
                HandleListViewClick(control);
            }

            base.OnClicked(controlId, control, actionType);
        }
        #endregion

        #region ISetupForm Members
        public string Author()
        {
            return "d-fader";
        }

        public bool CanEnable()
        {
            return true;
        }

        public bool DefaultEnabled()
        {
            return true;
        }

        public string Description()
        {
            return "Find everything you might possibly be looking for.";
        }

        public bool GetHome(out string strButtonText, out string strButtonImage, out string strButtonImageFocus, out string strPictureImage)
        {
            strButtonText = "Search music";
            strButtonImage = String.Empty;
            strButtonImageFocus = String.Empty;
            strPictureImage = String.Empty;
            return true;
        }

        public int GetWindowId()
        {
            return UID;
        }

        public bool HasSetup()
        {
            return true;
        }

        public string PluginName()
        {
            return GUIGlobalMusicSearch.GlobalSearchPluginName;
        }

        public void ShowPlugin()
        {
            FormGlobalSearchSettings form = new FormGlobalSearchSettings();
            form.ShowDialog();
        }
        #endregion

        #region IShowPlugin Members

        public bool ShowDefaultHome()
        {
            return true;
        }

        

        #endregion
    }
}
